package com.vueapi.schedule;

import com.alibaba.fastjson.JSON;
import com.vueapi.annotation.OperationLog;
import com.vueapi.constant.RedisEnum;
import com.vueapi.domain.HjArticle;
import com.vueapi.domain.HjWebsite;
import com.vueapi.domain.vo.SevenDayDataCountVO;
import com.vueapi.service.*;
import com.vueapi.utils.DateUtils;
import com.vueapi.utils.RedisUtils;
import com.vueapi.utils.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Classname ScheduleListening
 * @Description TODO
 * @Created by 赵宏建
 * @Date 2023/2/27 9:15
 * @Version 1.0.0
 */
@Component
@Slf4j
public class ScheduleListening {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private HjWebsiteService websiteService;

    @Autowired
    private HjArticleService articleService;

    @Resource
    private HjCommentService commentService;

    @Resource
    private HjTagService tagService;

    @Resource
    private VisitLogService visitLogService;

    @OperationLog(name = "每日七天数据更新")
    /**
     * 首页七天访问量数据，每天00:01点进行更新
     */
    @Scheduled(cron = "0 0 1 * * ?")
//    @Scheduled(cron = "*/5 * * * * ?")
    public void sevenDayDataListening(){
        log.info("========================sevenDayDataListening Start========================");
        List<Integer> blogAddCountList = articleService.getBlogAddCount();
        List<Integer> commentAddCountList = commentService.getCommentAddCount();
        List<Integer> tagAddCountList = tagService.getTagAddCount();
        List<Integer> visitAddCount = visitLogService.getVisitAddCount();

        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");
        ArrayList<String> sevenDayNameList = new ArrayList<>();

        for (int i = 7; i >= 1; i--) {
            Date today = DateUtils.calLastDay(i);
            sevenDayNameList.add(sdf.format(today));
        }

        SevenDayDataCountVO sevenDayDataCountVO = new SevenDayDataCountVO();
        sevenDayDataCountVO.setSevenDayName(sevenDayNameList);
        sevenDayDataCountVO.setBlogAddCount(blogAddCountList);
        sevenDayDataCountVO.setCommentAddCount(commentAddCountList);
        sevenDayDataCountVO.setMessageAddCount(commentAddCountList);
        sevenDayDataCountVO.setTagAddCount(tagAddCountList);
        sevenDayDataCountVO.setVisitAddCount(visitAddCount);

        redisTemplate.opsForValue().set("sevenDayData", JSON.toJSONString(sevenDayDataCountVO),1, TimeUnit.DAYS);
        log.info("========================sevenDayDataListening END========================");
    }

    /**
     * 站点访问量定时更新
     */
    @Scheduled(cron = "0 0/2 * * * ?")    // 2 分钟更新一次数据
    public void webSiteViewCountListening(){
        log.info("========================webSiteViewCountListening Start========================");
        log.info("开始监听 WebsiteViewCount 数据...");
        String redisViewCount = redisTemplate.opsForValue().get(RedisEnum.WEBSITE_VIEW_COUNT);
        if(StringUtils.isEmpty(redisViewCount)){
            log.info("未从 Redis 中读取到 WebsiteViewCount 数据...监听结束...");
            log.info("========================webSiteViewCountListening End========================");
            return;
        }
        int viewCount = Integer.parseInt(redisViewCount);
        log.info("新增访问量：" + redisViewCount);

        // 如果数据为0，就是没有新增，直接结束
        if(viewCount <= 0){
            log.info("========================webSiteViewCountListening End========================");
            return;
        }

        HjWebsite website = websiteService.getById("1");
        website.setViewCount(website.getViewCount() + viewCount);
        websiteService.updateById(website);
        redisTemplate.opsForValue().decrement(RedisEnum.WEBSITE_VIEW_COUNT,viewCount);

        log.info("WebsiteViewCount 数据更新完成...");
        log.info("========================webSiteViewCountListening End========================");
    }

    /**
     * 文章访问量定时更新
     */
    @Scheduled(cron = "0 0/5 * * * ?")    // 5 分钟更新一次数据
    public void articleViewCountListening(){
        log.info("========================articleViewCountListening Start========================");
        log.info("开始监听 ArticleViewCount 数据...");
        Set<String> keys = redisTemplate.keys(RedisEnum.ARTICLE_VIEW_COUNT + "*");
        ArrayList<Integer> data = new ArrayList<>();

        if(keys == null || keys.isEmpty()){
            log.info("未从 Redis 中读取到 ArticleViewCount 数据...监听结束...");
            log.info("========================articleViewCountListening End========================");
            return;
        }

        for (String key : keys) {
            int id = Integer.parseInt(key.replace(RedisEnum.ARTICLE_VIEW_COUNT, ""));
            String redisViewCount = redisTemplate.opsForValue().get(RedisEnum.ARTICLE_VIEW_COUNT + id);

            // 如果为空则进入下一轮循环
            if(StringUtils.isEmpty(redisViewCount)) {
                continue;
            }

            // 如果 小于0 直接进入下一轮循环
            int viewCount = Integer.parseInt(redisViewCount);
            if(viewCount <= 0){
                continue;
            }

            HjArticle article = articleService.getById(id);
            article.setViewCounts(article.getViewCounts() + viewCount);
            articleService.updateById(article);

            // 更新完后清空数据
            redisTemplate.opsForValue().decrement(RedisEnum.ARTICLE_VIEW_COUNT + id,viewCount);
            data.add(id);
        }

        log.info(data + "文章浏览量进行了更新...");
        log.info("ArticleViewCount 数据更新完成...");
        log.info("========================articleViewCountListening End========================");
    }
}
